﻿using Microsoft.Extensions.DependencyInjection;
using Modules.SMS.Entitys;
using Modules.SMS.EventArgs;
using Modules.SMS.Repositories;
using PmSoft;
using PmSoft.Events;
using PmSoft.Exceptions;

namespace Modules.SMS
{
    /// <summary>
    /// 短信记录服务类
    /// </summary>
    [UseDI(ServiceLifetime.Scoped)]
    public class SmsSendLogService
    {
        private readonly SmsSendLogRepository smsSendLogRepository;
        private readonly IEventBus eventBus;

        public SmsSendLogService(SmsSendLogRepository smsSendLogRepository, IEventBus eventBus)
        {
            this.smsSendLogRepository = smsSendLogRepository;
            this.eventBus = eventBus;
        }

  
        /// <summary>
        /// 根据短信模型发送
        /// </summary>
        /// <param name="mobile"></param>
        /// <param name="model"></param>
        public void Send(string mobile, ISmsModel model)
        {
            Send(new SmsSendLog
            {
                Phone = mobile,
                MsgType = model.Type,
                MsgContent = model.Message,
                VerificationCode = model.Code
            });
        }

        /// <summary>
        /// 根据短信日志发送短信
        /// </summary>
        /// <param name="smsSendLog"></param>
        public void Send(SmsSendLog smsSendLog)
        {
            CheckAndThrowIfSendSms(smsSendLog.Phone, smsSendLog.MsgType);
            Create(smsSendLog);
            eventBus.PublishTo(this, new SMSSendEventArgs(smsSendLog.MsgId));
        }

        /// <summary>
        /// 创建短信发送记录
        /// </summary>
        /// <param name="smsSendLog"></param>
        public void Create(SmsSendLog smsSendLog)
        {
            if (string.IsNullOrEmpty(smsSendLog.MsgId))
                smsSendLog.MsgId = Guid.NewGuid().ToString().Replace("-", "");
            smsSendLogRepository.Insert(smsSendLog);
        }

        /// <summary>
        /// 更新
        /// </summary>
        /// <param name="smsSendLog"></param>
        public void Update(SmsSendLog smsSendLog)
        {
            smsSendLogRepository.Update(smsSendLog);
        }

        /// <summary>
        /// 验证是否存在验证码
        /// </summary>
        /// <param name="mobile"></param>
        /// <param name="inputCode"></param>
        /// <param name="msgType"></param>
        /// <returns></returns>
        public bool Validate(string mobile, string inputCode, MsgType? msgType)
        {
            if (string.IsNullOrEmpty(inputCode))
                return false;
            var logs = GetSendLogs(mobile, new SMSSendQuery { Type = msgType, EndDate = DateTime.Now.AddMinutes(-10) });//获取十分钟内短信
            var log = logs.FirstOrDefault(m => m.VerificationCode == inputCode && !m.IsUsed);
            if (log != null)
            {
                log.IsUsed = true;
                smsSendLogRepository.Update(log);
                return true;
            }
            return false;
        }

        /// <summary>
        /// 检查是否能发送短信，不能发送则抛出异常
        /// </summary>
        /// <param name="mobile"></param>
        /// <param name="msgType"></param>
        /// <exception cref="BusinessException"></exception>
        public void CheckAndThrowIfSendSms(string mobile, MsgType? msgType)
        {
            var count = TotalSendCount(mobile, new SMSSendQuery { Type = msgType, EndDate = DateTime.Now.AddMinutes(-10) });//获取十分钟内短信
            if (count >= 5)
                throw new BusinessException("10分钟内不能向同一手机号码发送超过5条短信");

        }

        public SmsSendLog? GetLog(string msgId)
        {
            return smsSendLogRepository.Get(msgId);
        }

        /// <summary>
        /// 查询指定手机号码发送短信记录
        /// </summary>
        /// <param name="mobile"></param>
        /// <param name="query"></param>
        /// <returns></returns>
        public IEnumerable<SmsSendLog> GetSendLogs(string mobile, SMSSendQuery query)
        {
            return smsSendLogRepository.GetSendLogs(mobile, query);
        }

        /// <summary>
        /// 合计发送数量
        /// </summary>
        /// <param name="mobile"></param>
        /// <param name="query"></param>
        /// <returns></returns>
        public int TotalSendCount(string mobile, SMSSendQuery query)
        {
            return smsSendLogRepository.TotalSendCount(mobile, query);
        }

        public IPagedList<SmsSendLog> GetSendLogs(SmsPageQuery query, int pageIndex, int pageSize)
        {
            return smsSendLogRepository.GetSendLogs(query, pageIndex, pageSize);
        }
    }
}